import Fly from "flyio/dist/npm/wx";
import Vue from "vue";

let instance = null;
let log = console.log;


const loginUrl = "/wxapp/login";
const registerUrl = "/wxapp/register";
const baseUrl = "http://111.230.169.95";
const appid = "wx206e969ae511aa81";
const tokenKey = "nearbyToken";

class Network {

  constructor() {
    if (!instance) {
      instance = this;
      this.token = "";
      this.fly = new Fly();
      this.fly.config.headers = { "x-tag": "hoolly-fly" };
      this.fly.config.baseURL = baseUrl;
      this.tokenFly = new Fly();
      this.hackFly = new Fly();
      this.hackFly.config.headers = { "x-tag": "unlimit" };
      this.tokenFly.config = this.fly.config;
      this.wxLogin = wx.pro.login;
      this.getSetting = wx.pro.getSetting;
      this.wxGetUserInfo = wx.pro.getUserInfo;
      this.token = wx.getStorageSync(tokenKey);
      this.pendingRequest = null;
      Vue.prototype.http = this.fly;
      Vue.prototype.hackFly = this.hackFly;
      this.init_request_interceptors();
      this.init_response_interceptors();
    }
    return instance;
  }


  init_request_interceptors() {
    this.fly.interceptors.request.use((request) => {
      log(`发起请求：path:${request.url}，baseURL:${request.baseURL}`);
      request.headers["x-ts"] = new Date().getTime();
      request.headers["x-request-id"] = Network.gen_x_request_id(8);
      if (!this.token) {
        log("token不存在，需要请求token");
        this.fly.lock();
        return this.wxLogin().then(result => {
          if (result.code) {
            log(`wx登录成功 result:[ ${result}]`);
            return this.tokenFly.get(loginUrl, {
              code: result.code,
              appid: appid
            });
          }
        }).then(result => {//请求成功，拿到token
          this.token = result.data.token;
          wx.setStorageSync(tokenKey, this.token);
          request.headers["Authorization"] = this.token;
          this.fly.unlock();
          return request;
        })
          .catch(reason => {
            return Promise.reject(reason);
          });
      } else {
        request.headers["Authorization"] = this.token;
      }
    });
    this.tokenFly.interceptors.request.use((request => {
      request.headers["x-ts"] = new Date().getTime();
      request.headers["x-request-id"] = Network.gen_x_request_id(8);
      request.headers["Authorization"] = this.token;
    }));
  }

  /**
   * 遇到一个坑 TypeError: _this2.tokenFly.get(...).then(...).finally is not a function
   * 所以换成then,catch的写法
   *
   * https://stackoverflow.com/questions/38892549/finally-is-not-a-function-when-using-async-redux-actions-with-promises
   */
  init_response_interceptors() {

    //  response interceptors
    this.fly.interceptors.response.use(
      (response) => {
        log("interceptors.response", response);
        return response.data.data;
      },
      (err) => {
        this.pendingRequest = err.request;
        if (err.status == 401) {//用户已注册token失效，需要重新续期
          log("token过期，需要换token", err);
          this.fly.lock(); //锁定响应拦截器
          return this.wxLogin().then(result => {
            return this.tokenFly.get(loginUrl, {
              code: result.code,
              appid: appid
            });
          })
            .then((d) => {
              this.token = d.data.token;
              wx.setStorageSync(tokenKey, this.token);
              log("token已更新，值为: " + this.token);
              this.fly.unlock();
              log(`将会重新请求：path:${this.pendingRequest.url}，baseURL:${this.pendingRequest.baseURL}`);
              return this.fly.request(this.pendingRequest);
            })
            .catch((reason) => {
              this.fly.unlock();
              log(`token 刷新失败：status:${reason.status}, response.data:${reason.response.data}`);
              return Promise.reject(reason);
            });
        } else if (err.status == 307) {//需要用户去注册
          this.fly.lock();
          this.getSetting().then((res) => {
            if (res && res.authSetting && res.authSetting["scope.userInfo"]) {//用户已经授权
              return this.wxGetUserInfo({
                withCredentials: true
              });
            } else {//用户没有授权，需要弹出对话框让用户授权
              Network.showGetUserInfoTips();
              this.fly.unlock();
              return Promise.reject({ "err": "用户没有授权" });
            }
          }).then(result => {
            if (result.encryptedData && result.iv) {
              log("请求用户信息成功,开始注册");
              return this.tokenFly.post(registerUrl, {
                encryptedData: result.encryptedData,
                iv: result.iv
              });
            }
          }).then(result => {
            log(`注册成功，结果[${result}]`);
            this.fly.unlock();
            log(`将会重新请求：path:${this.pendingRequest.url}，baseURL:${this.pendingRequest.baseURL}`);
            return this.fly.request(this.pendingRequest);
          }).catch(reason => {
            this.fly.unlock();
            return Promise.reject(reason);
          });
        }
      }
    );
  }

  static showGetUserInfoTips() {
    // wx.openSetting();
    wx.redirectTo({
      url: "/pages/modal/main"
    });
  }

  static gen_x_request_id(len) {
    var chars = "abcdefhijkmnoprstwxyz0123456789";
    var maxPos = chars.length;
    var request_id = "";
    for (let i = 0; i < len; i++) {
      request_id += chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return request_id;
  }
}

//https://k94n.com/es6-modules-single-instance-pattern   这样所有地方都是这个单例
let network = new Network();
export default network;
